package com.vecspace.dayu.code.source.model;

import java.util.*;
import java.util.stream.Collectors;

import javax.persistence.Transient;

import com.vecspace.dayu.code.ui.model.ColumnVO;
import com.vecspace.dayu.code.ui.pojo.DataGrid;
import com.vecspace.exception.HException;
import org.apache.commons.lang3.StringUtils;

import com.vecspace.database.model.QuerySQL;
import com.vecspace.dayu.code.consts.DbType;
import com.vecspace.dayu.code.pojo.DataColumn;
import com.vecspace.dayu.code.pojo.DataTable;
import com.vecspace.dayu.code.pojo.Func;
import com.vecspace.dayu.code.pojo.Project;
import com.vecspace.dayu.code.ui.pojo.Form;
import com.vecspace.utils.Assert;
import com.vecspace.utils.Convert;

/**数据表级的模板参数
 * 
 * @version 1.0
 * @author wanghua
 */
public class SourceCodeParamsBaseTable implements Cloneable{

	public SourceCodeParamsBaseTable() {

	}

	private Project project;
	private Func func;
	private String author;
	private String nowTime;
	private String sysName;

	private DataTable table;
	/**本表是否是树形结构*/
	private boolean isTree;

	/**本表自身的上级字段，只有this.isTree==true时有效*/
	private DataColumn parentColumn;

	//private final List<DataGridColumn> aggregateColumns = new ArrayList<>();//聚合字段(sum,agv,max...)
	//private final List<DataGridColumn> aggregateGroupColumns = new ArrayList<>();//分组字段（group by）

	/**本表(this.table)中，关联目录表(或者主表)的字段*/
	private DataColumn foreignColumn;//foreignColumn;
	/**本表(this.table)关联的目录表(或者主表)*/
	private DataTable foreignTable;
	
	/**本表(this.table)关联的上级表（foreignTable）是否是树结构（递归表）*/
	private boolean catalogIsTree;

	/**本表(this.table)关联的叶子表（当本表为目录表时）*/
	private DataTable leafTable;
	private boolean showLeaf;

	/**本表(this.table)的表格对象*/
	private DataGrid dataGrid;

	/**本表(this.table)的表单对象*/
	private Form form;

	/**本表(this.table)的字段列表*/
	private List<ColumnVO> columns;
	
	private boolean useRecurseQuery;//是否使用递归查询

	/**检查参数配置是否合理，不合理则抛出异常
	 *
	 * @return
	 * @throws HException
	 */
	public boolean checkConfig() throws HException {
		if(getIsTree()){
			Assert.throwz(parentColumn != null, String.format("自递归表(%s)必须设置父ID字段",table.getTableName()));
			Assert.throwz(StringUtils.isNotBlank(table.getNameColumnName()), String.format("自递归表(%s)必须设置名称字段",table.getTableName()));
		}
		if(getCatalogIsTree()){//父表是目录表
			Assert.throwz(StringUtils.isNotBlank(foreignTable.getNameColumnName()), String.format("目录表(%s)必须设置名称字段",foreignTable.getTableName()));
			Assert.throwz(StringUtils.isNotBlank(foreignTable.getParentIdColumnName()), String.format("目录表(%s)必须设置父ID字段",foreignTable.getTableName()));
		}

		if(useRecurseQuery){
			if(!getIsTree()) {
				Assert.throwz(foreignTable != null && foreignColumn != null, String.format("表(%s)使用递归查询，关联的目录表和目录字段不能为null",table.getTableName()));
			}
		}

		if(foreignColumn != null && foreignTable == null){
			throw new HException(String.format("表(%s)：catalogColumn不为空时，catalogTable也不能为空",table.getTableName()));
		}
		if(foreignTable != null && foreignColumn == null){
			throw new HException(String.format("表(%s)：catalogTable不为空时，catalogColumn也不能为空",table.getTableName()));
		}
		return true;
	}

	public Project getProject() {
		return project;
	}
	public void setProject(Project project) {
		this.project = project;
	}
	public Func getFunc() {
		return func;
	}
	public void setFunc(Func func) {
		this.func = func;
	}

	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getNowTime() {
		return nowTime;
	}
	public void setNowTime(String nowTime) {
		this.nowTime = nowTime;
	}
	public String getSysName() {
		return sysName;
	}
	public void setSysName(String sysName) {
		this.sysName = sysName;
	}
	
	public DataTable getTable() {
		return table;
	}
	public void setTable(DataTable table) {
		this.table = table;
	}
	/**本表是否是树形结构*/
	public Boolean getIsTree() {
		return isTree;
	}
	/**本表是否是树形结构*/
	public void setIsTree(Boolean isTree) {
		if(isTree == null){
			this.isTree = false;
		}else {
			this.isTree = isTree;
		}
	}
	/**本表(this.table)关联的上级表（foreignTable）是否是树结构（递归表）*/
	public boolean getCatalogIsTree() {
		return catalogIsTree;
	}
	/**本表(this.table)关联的上级表（foreignTable）是否是树结构（递归表）*/
	public void setCatalogIsTree(boolean catalogIsTree) {
		this.catalogIsTree = catalogIsTree;
	}

	/**本表自身的上级字段(同parentColumnId)，只有isTree==true时有效*/
	public DataColumn getParentColumn() {
		return parentColumn;
	}
	/**本表自身的上级字段(同parentColumnId)，只有isTree==true时有效*/
	public void setParentColumn(DataColumn parentColumn) {
		this.parentColumn = parentColumn;
	}

	/**本表(this.table)中，关联目录表(或者主表)的字段*/
	public DataColumn getForeignColumn() {
		return foreignColumn;
	}
	/**本表(this.table)中，关联目录表(或者主表)的字段*/
	public void setForeignColumn(DataColumn foreignColumn) {
		this.foreignColumn = foreignColumn;
	}

	/**本表(this.table)关联的目录表(或者主表)*/
	public DataTable getForeignTable() {
		return foreignTable;
	}

	/**本表(this.table)关联的目录表(或者主表)*/
	public void setForeignTable(DataTable foreignTable) {
		this.foreignTable = foreignTable;
	}
	/**本表(this.table)关联的叶子表（当本表为目录表时）*/
	public DataTable getLeafTable() {
		return leafTable;
	}
	/**本表(this.table)关联的叶子表（当本表为目录表时）*/
	public void setLeafTable(DataTable leafTable) {
		this.leafTable = leafTable;
	}

	public boolean isShowLeaf() {
		return showLeaf;
	}

	public void setShowLeaf(Boolean showLeaf) {
		if(showLeaf == null)this.showLeaf = false;
		else this.showLeaf = showLeaf;
	}

	/**是否关联树结构 本表存在父表并且父表是树结构*/
	public boolean getLinkToTree() {
		return foreignTable != null && StringUtils.isNotBlank(getForeignTable().getParentIdColumnName()) && foreignColumn!=null;
	}

	public List<ColumnVO> getColumns() {
		return columns;
	}

	public void setColumns(List<ColumnVO> columns) {
		this.columns = columns;
	}

	public List<ColumnVO> getFormFields(){
		if(columns == null)return Collections.emptyList();
		List<ColumnVO> formFields = columns.stream().filter(col -> col.getIsFormField()).collect(Collectors.toList());
		formFields.sort(new Comparator<ColumnVO>() {
			@Override
			public int compare(ColumnVO o1, ColumnVO o2) {
				if(o1.getFormFieldOrdnum() == null)return -1;
				if(o2.getFormFieldOrdnum() == null)return 1;
				return o1.getFormFieldOrdnum().compareTo(o2.getFormFieldOrdnum());
			}
		});
		return formFields;
	}

	public List<ColumnVO> getGridColumns(){
		if(columns == null)return Collections.emptyList();
		List<ColumnVO> gridColumns =  columns.stream().filter(col->col.getIsGridColumn()).collect(Collectors.toList());
		gridColumns.sort(new Comparator<ColumnVO>() {
			@Override
			public int compare(ColumnVO o1, ColumnVO o2) {
				if(o1.getGridColumnOrdnum() == null)return -1;
				if(o2.getGridColumnOrdnum() == null)return 1;
				return o1.getGridColumnOrdnum().compareTo(o2.getGridColumnOrdnum());
			}
		});
		return gridColumns;
	}

	public List<ColumnVO> getQueryColumns(){
		if(columns == null)return Collections.emptyList();
		List<ColumnVO> queryColumns =  columns.stream().filter(col->col.getQueryField() != null && col.getQueryField()==true).collect(Collectors.toList());
		if(this.getLinkToTree()) {
			queryColumns = queryColumns.stream().filter(col->!col.getName().equalsIgnoreCase(foreignColumn.getName())).collect(Collectors.toList());
		}
		queryColumns.sort(new Comparator<ColumnVO>() {
			@Override
			public int compare(ColumnVO o1, ColumnVO o2) {
				if(o1.getGridColumnOrdnum() == null)return -1;
				if(o2.getGridColumnOrdnum() == null)return 1;
				return o1.getGridColumnOrdnum().compareTo(o2.getGridColumnOrdnum());
			}
		});
		return queryColumns;
	}

	public Form getForm() {
		return form;
	}
	public void setForm(Form form) {
		this.form = form;
	}

	public DataGrid getDataGrid() {
		return dataGrid;
	}

	public void setDataGrid(DataGrid dataGrid) {
		this.dataGrid = dataGrid;
	}

	/**返回有聚合函数的原始字段
	 **/
	public List<ColumnVO> getAggregateSrcColumns() {
		if(columns == null)return Collections.emptyList();
		List<ColumnVO> groupByColumns = new ArrayList<>();
		for(ColumnVO col : columns){
			if(StringUtils.isNotBlank(col.getAggregateFunc())) {
				if(col.getAggregateColumns().size() > 0) {
					groupByColumns.add(col);
				}
			}
		}
		return groupByColumns;
	}

	/**返回所有解析后的聚合字段（一个原始字段解析后可以对应多个聚合字段，必须salary字段，有agv，max两个聚合函数，则对应2个解析后的字段。）
	 *
	 * @author wanghua
	 * @date 2021/11/9  14:18
	 * @return java.util.List<com.vecspace.dayu.code.pojo.DataColumn>
	 **/
	public List<DataColumn> getAllAggregateColumns(){
		List<DataColumn> aggColumnsAll = new ArrayList<>();
		for(ColumnVO col : getAggregateSrcColumns()){
			aggColumnsAll.addAll(col.getAggregateColumns());
		}
		return aggColumnsAll;
	}

	/**返回分组字段
	 *
	 * @author wanghua
	 * @date 2021/11/8  14:10
	 * @return java.util.List<com.vecspace.dayu.code.ui.model.ColumnVO>
	 **/
	public List<ColumnVO> getGroupByColumns() {
		if(columns == null)return Collections.emptyList();
		List<ColumnVO> groupByColumns = new ArrayList<>();
		for(ColumnVO col : columns){
			if(col.getAggregateGroup() != null && col.getAggregateGroup() == true){
				if(StringUtils.isNotBlank(col.getCodeType())) {
					groupByColumns.add(col);
				}else{
					throw new HException("只有codetype不为空的字段才能设置为分组字段");
				}
			}
		}
		return groupByColumns;
	}

//	/**获取聚合字段，比如 "SUM(SALARY),AVG(SALARY)"
//	 *
//	 * @return
//	 * @author wanghua
//	 */
//	public String getAggregateSql() {
//		List<ColumnVO> aggregateColumns = getAggregateColumns();
//		if(aggregateColumns == null || aggregateColumns.size() == 0)return "";
//		StringBuilderEx sql = new StringBuilderEx();
//		for(ColumnVO aggregateColumn : aggregateColumns) {
//			String aggregateFunc = aggregateColumn.getAggregateFunc();
//			if(aggregateFunc != null && aggregateFunc.length() > 0) {
//				String[] funcNames = aggregateFunc.split(",");//SUM,AVG,MAX,MIN
//				String columnName = aggregateColumn.getColumnName();
//				for(String funcName : funcNames) {
//					if(StringUtils.isNotBlank(funcName)) {
//						sql.append(funcName).append("(").append(columnName).append("),");
//					}
//				}
//			}
//		}
//		if(sql.length() > 0) {
//			sql.deleteCharAt(sql.length() - 1);
//		}
//		return sql.toString();
//	}
	
//	/**获取分组字段,比如 "YEAR,DEPT_ID"
//	 *
//	 * @return
//	 * @author wanghua
//	 */
//	public String getGroupSql() {
//		List<ColumnVO> aggregateGroupColumns = getAggregateGroupColumns();
//		if(aggregateGroupColumns == null || aggregateGroupColumns.size() == 0)return "";
//		StringBuilderEx sql = new StringBuilderEx();
//		for(ColumnVO groupColumn : aggregateGroupColumns) {
//			sql.append(groupColumn.getColumnName()).append(",");
//		}
//		if(sql.length() > 0) {
//			sql.deleteCharAt(sql.length() - 1);
//		}
//		return sql.toString();
//	}
		
	/** 是否使用递归查询 */
	public Boolean getUseRecurseQuery() {
		return useRecurseQuery;
	}
	public void setUseRecurseQuery(Boolean useRecurseQuery) {
		if(useRecurseQuery == null){
			this.useRecurseQuery = false;
		}else {
			this.useRecurseQuery = useRecurseQuery;
		}
	}

	/**Oracle的递归查询子句
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月26日 上午10:50:29
	 */
	public String getConnectBySql() {
		//SELECT * FROM TB where sex='1' START WITH ID = 1 CONNECT BY PRIOR ID=PID; // 查子节点：prior ID=PID， 查父节点：ID = prior PID
		if(foreignTable == null)return "";
		Assert.throwz(foreignTable.getParentColumn() != null, "父节点字段不能为空");
		
		String tableName = foreignTable.getTableName();
		String idColumn = foreignTable.getIdColumnName();
		String parentIdColumn = foreignTable.getParentColumn().getColumnName();
		String sql = String.format("SELECT * FROM %s START WITH ID = ? CONNECT BY PRIOR %s=%s", tableName,idColumn,parentIdColumn);
		return sql;
	}
	
	/**目录表的递归查询子句(mysql和postgresql)
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月26日 上午10:50:43
	 */
	public String getCatalogRecurseCteSql() {
/***********************************************************
	     with recursive cte_employees as(
	        select r1.id,r1.parent_id,r1.name_ from T_DEMO_DEPARTMENT r1  where r1.id = ?
	        union all
	        select r2.id,r2.parent_id,r2.name_ from T_DEMO_DEPARTMENT r2 join cte_employees cte on cte.id = r2.parent_id
	    )
 **************************************************************/
		if(foreignTable == null)return "";
		Assert.throwz(foreignTable.getParentColumn() != null, "父节点字段不能为空");
		Assert.throwz(foreignTable.getNameColumn() != null, "名称字段不能为空");
		
		String tableName = foreignTable.getTableName();
		String idColumn = foreignTable.getIdColumnName();
		String parentIdColumn = foreignTable.getParentColumn().getColumnName();
		String parentNameColumn = foreignTable.getNameColumn().getColumnName();
		
		StringBuilder sqlText = new StringBuilder(256);
		sqlText.append("with recursive cte1 as(\n")
		.append(String.format("select r1.%s,r1.%s,r1.%s from %s r1  where r1.%s = ?", 
				idColumn,parentIdColumn,parentNameColumn,tableName,idColumn))		
        .append(" union all\n")
        .append(String.format("select r2.%s,r2.%s,r2.%s from %s r2 join cte1 on cte1.%s = r2.%s)",
        		idColumn,parentIdColumn,parentNameColumn,tableName,idColumn,parentIdColumn));
		
        return sqlText.toString();
	}
	
	/**本表的递归查询子句(mysql和postgresql)
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月26日 上午10:50:43
	 */
	public String getSelfRecurseCteSql() {
/***********************************************************
	     with recursive cte_employees as(
	        select r1.id,r1.parent_id,r1.name_ from T_DEMO_DEPARTMENT r1  where r1.id = ?
	        union all
	        select r2.id,r2.parent_id,r2.name_ from T_DEMO_DEPARTMENT r2 join cte_employees cte on cte.id = r2.parent_id
	    )
 **************************************************************/
		Assert.throwz(table.getParentColumn() != null, "父节点字段不能为空");
		String tableName = table.getTableName();
		String idColumn = table.getIdColumnName();
		String parentIdColumn = table.getParentColumn().getColumnName();
		
		StringBuilder sqlText = new StringBuilder(256);
		sqlText.append("with recursive cte1 as(\n")
		.append(String.format("select * from %s r1  where r1.%s = ?", tableName,idColumn))		
        .append("union all\n")
        .append(String.format("select from %s r2 join cte1 on cte1.%s = r2.%s", tableName,idColumn,parentIdColumn));
		
        return sqlText.toString();
	}
	
	private QuerySQL querySQL;
	private QuerySQL recursionQuerySQL;
	@Transient
	public QuerySQL getQuerySQL() {
		if(querySQL == null) {
			querySQL = buildQuerySql();
		}
		return querySQL;
	}

	@Transient
	public QuerySQL getRecursionQuerySQL() {
		if(recursionQuerySQL == null) {
			recursionQuerySQL = buildRecursionQuerySql();
		}
		return recursionQuerySQL;
	}
	
//	@Transient
//	public void setQuerySQL(QuerySQL querySQL) {
//		this.querySQL = querySQL;
//	}
	
//	/**目录表递归查询（当本表为叶子表，目录表有递归字段，本表有ParentColumn）
//	 *
//	 * @return
//	 * @author wanghua
//	 * @reviewer
//	 * @createTime 2021年10月25日 下午4:45:57
//	 */
//	public boolean getForeignTableRecurseValid() {
//		if(this.foreignTable == null)return false;
//		if(this.foreignTable.getParentColumn() == null)return false;
//		if(this.table.getParentColumn() == null)return false;
//		return true;
//	}
	
	/**本表自身是否递归查询（本表属于目录类型表，有递归字段）
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月26日 上午11:49:44
	 */
	public boolean getSelfRecurseValid() {
		if(foreignTable != null && !foreignTable.getId().equals(table.getId()))return false;//当存在目录表时，本表不可能自递归
		if(table.getParentColumn() != null)return true;
		return false;
	}
	
	private QuerySQL buildQuerySql() {
		List<DataColumn> columns = table.getColumns();
		String tableName = table.getTableName();

		QuerySQL querySQL = new QuerySQL();
		if (columns == null || columns.size() == 0) return querySQL;
		StringBuilder columnsText = new StringBuilder(1024);
		StringBuilder joinSqlText = new StringBuilder(1024);


		if(foreignColumn != null){//关联目录表的字段添加到join中 注意：catalogTable固定别名为t2
			columnsText.append("t2").append(".").append(foreignTable.getNameColumnName()).append(" ").append(foreignColumn.getRefIdColumnAliasName()).append(",");
			joinSqlText.append("\r\n left join ").append(foreignTable.getTableName()+" t2").append(" on t1.").append(foreignColumn.getColumnName());
			joinSqlText.append("=").append("t2").append(".").append(foreignTable.getIdColumnName());
		}

		for (DataColumn col : columns) {
			//检查是否是关联目录表的字段，如果是，则跳过(在上面已经添加过了)
			if(foreignColumn != null && foreignColumn.getColumnName().equalsIgnoreCase(col.getColumnName())){
				continue;
			}

			String colName = col.getColumnName();
			columnsText.append("t1.").append(colName).append(",");

			String refTableName = col.getRefTableName();
			String refIdColumnName = col.getRefIdColumn();
			String refNameColumn = col.getRefNameColumn();
			String refNameColumnAliasName = col.getRefNameColumnAliasName();

			if (foreignColumn != null && foreignTable != null && col.getId().equals(foreignColumn.getId())) {
				if (StringUtils.isBlank(refTableName)) {
					refTableName = foreignTable.getTableName();
					refIdColumnName = foreignTable.getIdColumnName();
					refNameColumn = foreignTable.getNameColumnName();
				}
			}

			if (StringUtils.isNotBlank(refTableName) && StringUtils.isNotBlank(refIdColumnName) && StringUtils.isNotBlank(refNameColumn))//外键
			{
				if (StringUtils.isBlank(refNameColumnAliasName)) {//主键名称字段别名为空的情况下，构造一个以外键ID字段+"NAME"的别名
					if (refIdColumnName.toUpperCase().endsWith("_ID")) {
						refNameColumnAliasName = refIdColumnName.substring(0, refIdColumnName.length() - 3) + "_NAME";
					} else {
						refNameColumnAliasName = refIdColumnName + "_NAME";
					}
				}

				String refNameColumnSql = refNameColumn + " " + refNameColumnAliasName;//名称字段
				String refColumns = refNameColumnSql;
				columnsText.append(refTableName).append(".").append(refColumns).append(",");
				joinSqlText.append("\r\n left join ").append(refTableName).append(" on t1.").append(colName);
				joinSqlText.append("=").append(refTableName).append(".").append(refIdColumnName);
			}
		}

		columnsText.delete(columnsText.length() - 1, columnsText.length());
		int columnCount = 0;
		for (int i = 0; i < columnsText.length(); ++i) {
			if (columnsText.charAt(i) == ',') {
				++columnCount;
				if (columnCount % 5 == 0) {
					columnsText.insert(i + 1, "\r\n");
					i += 2;
				}
			}
		}

		querySQL.setQueryColumns(columnsText.toString());
		querySQL.setTables(tableName + " t1 " + joinSqlText.toString());

		if (foreignColumn != null) {//存在目录表，本表（this.table）是叶子表
			//设置默认查询条件为目录ID
			querySQL.setWhere(String.format("t1.%s=?", this.foreignColumn.getColumnName()));
		}

		List<DataColumn> aggregateColumns = this.getAllAggregateColumns();//聚合字段
		if(aggregateColumns.size() > 0){
			//聚合字段
			String aggColumnNames = aggregateColumns.stream().map(col->col.getColumnName()+" "+col.getColumnAliasName()).collect(Collectors.joining(","));
			//分组字段
			List<ColumnVO> groupByColumns = this.getGroupByColumns();

			querySQL.addQueryGroup("total", "总计", "", aggColumnNames);
			if(groupByColumns.size() > 0){
				for(ColumnVO groupByColumn : groupByColumns){
					String groupName = groupByColumn.getVarName();
					String groupLabel = String.format("按%s统计",groupByColumn.getColumnCaption());
					String groupColumnNames = groupByColumn.getColumnName();
					querySQL.addQueryGroup(groupName, groupLabel, groupColumnNames, aggColumnNames);
				}
			}
		}

		return querySQL;
	}

	private QuerySQL buildRecursionQuerySql(){
		QuerySQL querySQL = this.buildQuerySql();

		String dbType = this.getDbType();
		//处理递归查询的情况
		if (catalogIsTree && useRecurseQuery) {//目录表递归，本表（this.table）是叶子表
			//本表和递归表（目录表）联合查询，必须设置固定查询条件，过滤掉join后目录表id为null的记录
			if (DbType.MySQL.equalsIgnoreCase(dbType) || DbType.PGSQL.equalsIgnoreCase(dbType)) {
				querySQL.setCteSql(this.getCatalogRecurseCteSql());
				String tables = querySQL.getTables();
				tables = tables.replaceFirst(" "+foreignTable.getTableName()+" ", " cte1 ");
				querySQL.setTables(tables);
				querySQL.setWhere(String.format("t2.%s is not null", foreignTable.getIdColumnName()));//过滤掉join后目录表id为null的记录
			} else if (DbType.Oracle.equalsIgnoreCase(dbType)) {
				String catalogTableNameUpper = foreignTable.getTableName().toUpperCase();
				String tables = querySQL.getTables();
				String connectSql = this.getConnectBySql();
				if (tables.toUpperCase().contains(" " + catalogTableNameUpper + " ")) {
					tables = tables.replace(" " + catalogTableNameUpper + " ", String.format("(%s) %s", connectSql, foreignTable.getTableName()));
				} else {
					tables += String.format(" left join (%s) t2 on t1.%s=t2.%s", connectSql,  table.getParentColumn().getColumnName(), foreignTable.getIdColumnName());
				}
				querySQL.setWhere(String.format("t2.%s is not null", foreignTable.getIdColumnName()));//过滤掉join后目录表id为null的记录
			}
		}
		if (getSelfRecurseValid()) {//本表(this.table)自身递归，没有目录表和叶子表
			if (DbType.MySQL.equalsIgnoreCase(dbType) || DbType.PGSQL.equalsIgnoreCase(dbType)) {
				querySQL.setCteSql(this.getSelfRecurseCteSql());
				querySQL.setTables("cte1 t1");
			} else if (DbType.Oracle.equalsIgnoreCase(dbType)) {
				String connectSql = this.getConnectBySql();
				querySQL.setTables(String.format("(%s) t1", connectSql));
			}
		}
		return querySQL;
	}

	/**单元格有下拉编辑框*/
	public boolean getHasCellEditMenu(){
		return columns.stream().filter(col->col.getEditMenu()==null?false:col.getEditMenu().booleanValue()).count() > 0;
	}

	public boolean getUpdateCellValueEnable(){
		boolean gridCellEditable = false;//单元格可编辑
		if(this.dataGrid != null) {
			if(this.dataGrid.getGridEditable() != null && this.dataGrid.getGridEditable() == true) {
				gridCellEditable = true;
			}
		}
		boolean cellMenu = getHasCellEditMenu();//单元格有下拉菜单
		return gridCellEditable || cellMenu;
	}
	public String getDbType() {
		String dbType = project.getDbType();
		if(StringUtils.isBlank(dbType))return "pssql";
		return dbType;
	}
	
	/**是否需要表单窗口：可以新增、编辑时才需要*/
	public boolean getShowFormDialog() {
		boolean showForm = false;
		if(dataGrid != null) {
			if(Convert.toBoolean(dataGrid.getToolbarAddBtn(),false) == true) {
				showForm = true;
			}
			if(Convert.toBoolean(dataGrid.getToolbarEditBtn(),false) == true) {
				showForm = true;
			}
			if(Convert.toBoolean(dataGrid.getOptrCellEditBtn(),false) == true) {
				showForm = true;
			}
		}
		return showForm;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj == null)return false;
		SourceCodeParamsBaseTable oth = (SourceCodeParamsBaseTable)obj;
		if(this.table == null || this.table.getId() == null)return false;
		if(oth.table == null || oth.table.getId() == null)return false;
		return this.table.getId().equals(oth.table.getId());
	}
	
	@Override
	public int hashCode() {
		if(this.table == null || this.table.getId() == null)return 0;
		return this.table.getId().hashCode();
	}
	
	@Override
	public SourceCodeParamsBaseTable clone() throws CloneNotSupportedException {
		return (SourceCodeParamsBaseTable)super.clone();
	}
}
